/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.util;

import cn.easyplatform.*;
import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.messages.AbstractResponseMessage;
import cn.easyplatform.messages.response.SimpleResponseMessage;
import cn.easyplatform.type.IResponseMessage;
import org.apache.shiro.session.UnknownSessionException;
import org.slf4j.Logger;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public final class MessageUtils {
    private MessageUtils() {
    }

    /**
     * @return
     */
    public static IResponseMessage<?> errorMessage() {
        return new SimpleResponseMessage("E001",
                I18N.getLabel("easyplatform.request.message.invalid"));
    }

    public static IResponseMessage<?> serviceNotFound() {
        return new SimpleResponseMessage("E002",
                I18N.getLabel("easyplatform.request.service.invalid"));
    }

    public static IResponseMessage<?> fatalMessage() {
        return new SimpleResponseMessage("E003",
                I18N.getLabel("easyplatform.request.service.fatal"));
    }

    public static IResponseMessage<?> projectNotFound() {
        return new SimpleResponseMessage("E004",
                I18N.getLabel("easyplatform.project.not.found"));
    }

    public static IResponseMessage<?> projectInvalid() {
        return new SimpleResponseMessage("E005",
                I18N.getLabel("easyplatform.project.invalid"));
    }

    public static IResponseMessage<?> projectDeviceInvalid() {
        return new SimpleResponseMessage("E006",
                I18N.getLabel("easyplatform.project.device.not.found"));
    }

    public static IResponseMessage<?> userNotFound(String msg) {
        return new SimpleResponseMessage("E007", I18N.getLabel(
                "easyplatform.user.not.found", msg));
    }

    public static IResponseMessage<?> userNotOrg(String msg) {
        return new SimpleResponseMessage("E008", I18N.getLabel(
                "easyplatform.user.not.org", msg));
    }

    public static IResponseMessage<?> entityNotFound(String type, String id) {
        return new SimpleResponseMessage("E009", I18N.getLabel(
                "entity.not.found", type, id));
    }

    public static IResponseMessage<?> scriptEngineSetError() {
        return new SimpleResponseMessage("E010",
                I18N.getLabel("script.engine.set.variable"));
    }

    public static IResponseMessage<?> scriptEngineEvalError(String source,
                                                            int line, int column, String msg) {
        if (source == null)
            source = "";
        else if (source.length() > 20)
            source = source.substring(20) + "...";
        return new SimpleResponseMessage("E011", I18N.getLabel(
                "script.engine.eval.error.1", source, line, column, msg));
    }

    public static IResponseMessage<?> scriptEngineEvalError(String source,
                                                            int line, String msg) {
        if (source == null)
            source = "";
        else if (source.length() > 20)
            source = source.substring(20) + "...";
        return new SimpleResponseMessage("E011", I18N.getLabel(
                "script.engine.eval.error.2", source, line, msg));
    }

    public static IResponseMessage<?> daoAccessError(String resourceId,
                                                     Object... args) {
        return new SimpleResponseMessage("E012",
                I18N.getLabel(resourceId, args));
    }

    public static IResponseMessage<?> dataListNotFound(String id) {
        return new SimpleResponseMessage("E013", I18N.getLabel(
                "datalist.not.found", id));
    }

    public static IResponseMessage<?> keyNotMatch(String table) {
        return new SimpleResponseMessage("E014", I18N.getLabel(
                "datalist.field.key.not.found", table));
    }

    public static IResponseMessage<?> recordNotFound(String table, String key) {
        return new SimpleResponseMessage("E015", I18N.getLabel(
                "table.record.not.found", table, key));
    }

    public static IResponseMessage<?> dataListNotSupport(String id) {
        return new SimpleResponseMessage("E016", I18N.getLabel(
                "context.datalist.not.support", id));
    }

    public static IResponseMessage<?> contextNotSupport(String id) {
        return new SimpleResponseMessage("E017", I18N.getLabel(
                "context.not.found", id));
    }

    public static IResponseMessage<?> swiftNotFound(String id) {
        return new SimpleResponseMessage("E018", I18N.getLabel(
                "swift.not.found", id));
    }

    public static IResponseMessage<?> userTryLoginFailed(String msg) {
        return new SimpleResponseMessage("E019", I18N.getLabel(
                "easyplatform.user.try.fail", msg));
    }

    public static IResponseMessage<?> userHasLogined(String msg) {
        return new SimpleResponseMessage("E020", I18N.getLabel(
                "easyplatform.user.login", msg));
    }

    public static IResponseMessage<?> userPasswordExpired(String msg) {
        return new SimpleResponseMessage("E021", I18N.getLabel(
                "easyplatform.user.expired", msg));
    }

    public static IResponseMessage<?> userAuthorizationError(String userId,
                                                             Exception e) {
        String msg = null;
        if (e instanceof EasyPlatformWithLabelKeyException) {
            EasyPlatformWithLabelKeyException ex = (EasyPlatformWithLabelKeyException) e;
            if (ex.getCause() != null) {
                Object[] args = new Object[ex.getArgs().length + 1];
                System.arraycopy(ex.getArgs(), 0, args, 0, ex.getArgs().length);
                args[ex.getArgs().length] = ex.getCause().getMessage();
                msg = I18N.getLabel(ex.getMessage(), args);
            } else
                msg = I18N.getLabel(ex.getMessage(), ex.getArgs());
        } else if (e instanceof EntityNotFoundException) {
            EntityNotFoundException ex = (EntityNotFoundException) e;
            return entityNotFound(ex.getType(), ex.getMessage());
        } else
            msg = e.getMessage();
        return new SimpleResponseMessage("E022", I18N.getLabel(
                "easyplatform.user.authorization", userId, msg));
    }

    public static IResponseMessage<?> userLoginConfirm(String msg) {
        return new SimpleResponseMessage("C000", I18N.getLabel(
                "easyplatform.user.confirm", msg));
    }

    public static IResponseMessage<?> byErrorCode(CommandContext cc,
                                                  RecordContext rc, String id, String code) {
        IResponseMessage<?> resp = new SimpleResponseMessage(code,
                cc.getMessage(code, rc));
        ((AbstractResponseMessage) resp).setId(id);
        return resp;
    }

    public static IResponseMessage<?> getMessage(Throwable e, Logger log) {
        if (e instanceof EntityNotFoundException)
            return entityNotFound(((EntityNotFoundException) e).getType(),
                    e.getMessage());
        if (e instanceof ScriptSetVariableException)
            return scriptEngineSetError();
        if (e instanceof ScriptRuntimeException)
            return new SimpleResponseMessage(
                    ((ScriptRuntimeException) e).getCode(), e.getMessage());
        if (e instanceof ScriptEvalException) {
            ScriptEvalException ex = (ScriptEvalException) e;
            if (ex.getColumn() >= 0)
                return scriptEngineEvalError(ex.getSource(), ex.getLine(),
                        ex.getColumn(), ex.getMessage());
            else
                return scriptEngineEvalError(ex.getSource(), ex.getLine(),
                        ex.getMessage());
        }
        if (e instanceof EasyPlatformWithLabelKeyException) {
            EasyPlatformWithLabelKeyException ex = (EasyPlatformWithLabelKeyException) e;
            if (ex.getCause() instanceof EasyPlatformWithLabelKeyException)
                ex = (EasyPlatformWithLabelKeyException) ex.getCause();
            if (ex.getCause() != null) {
                log.error(ex.getMessage(), ex.getCause());
                Object[] args = new Object[ex.getArgs().length + 1];
                System.arraycopy(ex.getArgs(), 0, args, 0, ex.getArgs().length);
                args[ex.getArgs().length] = ex.getCause().getMessage();
                String msg = I18N.getLabel(ex.getMessage(), args);
                if (ex.getLineNo() >= 0)
                    msg = "#" + ex.getLineNo() + ":" + ex.getSource() + ","
                            + msg;
                return new SimpleResponseMessage("E012", msg);
            } else {
                if (log.isErrorEnabled()) {
                    if (ex instanceof FieldNotFoundException)
                        log.error("error:" + ex.getArgs()[0], ex);
                    else
                        log.error("error", ex);
                }
                String msg = I18N.getLabel(ex.getMessage(), ex.getArgs());
                if (ex.getLineNo() >= 0)
                    msg = "#" + ex.getLineNo() + ":" + ex.getSource() + ","
                            + msg;
                return new SimpleResponseMessage("E012", msg);
            }
        }
        if (e instanceof ResponseMessageException)
            return ((ResponseMessageException) e).getResp();
        if (e instanceof InvalidUserException)
            return new SimpleResponseMessage("E000",
                    I18N.getLabel("easyplatform.user.invalid"));
        if (e instanceof UserOfflineException)
            return new SimpleResponseMessage("E000",
                    I18N.getLabel("easyplatform.user.offline"));
        if (e instanceof ServicePausedException)
            return new SimpleResponseMessage("e000", I18N.getLabel(e
                    .getMessage()));
        if (e instanceof UnknownSessionException)
            return new SimpleResponseMessage("E000",
                    I18N.getLabel("easyplatform.user.invalid"));
        if (log.isErrorEnabled())
            log.error("uncatch exception:", e);
        return fatalMessage();
    }

    public final static String getMessage(Exception ex) {
        String msg = null;
        if (ex instanceof ScriptEvalException) {
            ScriptEvalException e = (ScriptEvalException) ex;
            msg = I18N.getLabel("script.engine.eval.error.2",
                    e.getSource(), e.getLine(), ex.getMessage());
        } else if (ex instanceof ScriptRuntimeException) {
            msg = ((ScriptRuntimeException) ex).getCode() + ":"
                    + ex.getMessage();
        } else if (ex instanceof EasyPlatformWithLabelKeyException) {
            EasyPlatformWithLabelKeyException ge = (EasyPlatformWithLabelKeyException) ex;
            Object[] args = null;
            if (ex.getCause() != null) {
                args = new Object[ge.getArgs().length + 1];
                System.arraycopy(ge.getArgs(), 0, args, 0,
                        ge.getArgs().length);
                args[ge.getArgs().length] = ex.getCause().getMessage();
            } else
                args = ge.getArgs();
            msg = I18N.getLabel(ge.getMessage(), args);
            if (ge.getLineNo() >= 0)
                msg = "#" + ge.getLineNo() + ":" + ge.getSource() + ","
                        + msg;
        } else if (ex instanceof EntityNotFoundException) {
            EntityNotFoundException e = (EntityNotFoundException) ex;
            msg = I18N.getLabel("entity.not.found", e.getType(),
                    e.getMessage());
        } else {
            msg = ex.getMessage();
        }
        return msg;
    }
}
